package com.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class BaseDao<T> {
	private Class<T> classt;
	private String tableName;
	private Field[] field;
	private Method[] method;

	@SuppressWarnings("unchecked")
	public BaseDao() {
		// 获得反射参数
		ParameterizedType tp = (ParameterizedType) this.getClass().getGenericSuperclass();
		classt = (Class<T>) tp.getActualTypeArguments()[0];
		// 得到T类型的反射类型（让泛型可以得到更新的作用）
		tableName = classt.getSimpleName();
		// 获取泛型的简名（将数据库的表视为对象来看）
		field = classt.getDeclaredFields(); // 获取字段
		method = classt.getDeclaredMethods();
	}

	public void deleteSome(Object id) {
		// 通过id删除
		StringBuffer sql = new StringBuffer("delete from" + "");
		sql.append(tableName + " ");
	}

	public void upDate(T o) {
		StringBuffer sql = new StringBuffer("update ");
		sql.append(tableName + " set ");
		try {
			for (int i = 1; i < field.length; i++) {
				field[i].setAccessible(true);
				Object ob = field[i].get(o);
				if (ob != null) {
					sql = sql.append(field[i].getName() + "='").append(ob + "',");
				}
			}
			String sql1 = sql.toString().substring(0, sql.length() - 1);
			// 如果为空，sql语句中就填写空的空格
			// field[0].setAccessible(true);
			// System.out.println(sql.toString());
			// Object ob = field[0].get(o);
			// sql.append("where"+field[0].getName()+"="+ob);
			sql1 += " where AnnouncesID = '1'";
			// System.out.println(sql.toString());
			System.out.println(sql1);
			Connection con = DBUtil.getCon();
			PreparedStatement pstm = con.prepareStatement(sql1);
			pstm.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void insert(T o) {
		StringBuffer sql = new StringBuffer("insert into " + " ");
		sql.append(tableName);
		sql.append("(");
		int n = 0;
		try {
			for (int i = 1; i < field.length; i++) {
				// 首先需先拼字段 n作为计数拼value值
				field[i].setAccessible(true);
				// 让字段的值可以访问

				Object val = field[i].get(o);
				// 将传入的参数（也就是用户输入的内容在servlet中取得并存入到model层面）作为泛型取出来遍历
				if (val != null) {
					// 如果用户输入的不为空
					sql.append(field[i].getName()).append(",");
					n++;
				}
			}
			sql.replace(sql.length() - 1, sql.length(), ") ");
			sql.append("values(");

			System.out.println(sql.toString());
			for (int i = 1; i < field.length; i++) {
				field[i].setAccessible(true);
				Object val = field[i].get(o);
				if (val != null) {
					sql.append("'" + val + "'" + ",");
				}
			}
			sql.replace(sql.length() - 1, sql.length(), ")");
			System.out.println(sql);

			Connection con = DBUtil.getCon();
			PreparedStatement pstm = con.prepareStatement(sql.toString());

			pstm.executeUpdate();
		} catch (SecurityException e) {

			e.printStackTrace();
		} catch (IllegalArgumentException e) {

			e.printStackTrace();
		} catch (IllegalAccessException e) {

			e.printStackTrace();
		} catch (SQLException e) {

			e.printStackTrace();
		}

	}

	public List<T> query(T o) {
		List<T> list = new ArrayList<>();
		String sql = "select * from " + tableName;
		try {
			Connection conn = DBUtil.getCon();
			Statement stm = conn.createStatement();
			ResultSet rs = stm.executeQuery(sql);
			while (rs.next()) {
				T obj = classt.newInstance();
				// System.out.println(method.length);
				for (int i = 0; i < method.length; i++) {
					// System.out.println(method[i]);
					// for(int j=1;j<field.length;j++){
					//
					// }
					if (method[i].getName().contains("set")) {
						// System.out.println(method[i].getName());
						// 截取出对应的数据库的字段名
						String field = method[i].getName().substring(3);
						// 获取当前方法参数的类型，为了确定使用rs.getInt()或者使用rs.getString().
						String classType = method[i].getParameters()[0].getParameterizedType().toString();
						if (classType.contains("int")) {
							method[i].invoke(obj, rs.getInt(field)); // 用方法反调用
						} else if (classType.contains("String")) {
							method[i].invoke(obj, rs.getString(field));
						}
					}
				}
				list.add(obj);
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return list;
	}

	public List<T> byIDonSomething(T o) {
		List<T> list = new ArrayList<>();
		String sql = "select * from ";
		sql += tableName;
		sql += " where AnnouncesID='";
		try {
			Connection con = DBUtil.getCon();
			Statement stm = con.createStatement();
			field[0].setAccessible(true);
			Object ob = field[0].get(o);
			if (ob != null) {
				sql += ob+"'";
				
			}
			System.out.println(sql);
			ResultSet rs = stm.executeQuery(sql);
			while (rs.next()) {
				T obj = classt.newInstance();

				for (int i = 1; i < method.length; i++) {

					if (method[i].getName().contains("set")) {
						// System.out.println(method[i].getName());
						// 截取出对应的数据库的字段名
						String field = method[i].getName().substring(3);
						// 获取当前方法参数的类型，为了确定使用rs.getInt()或者使用rs.getString().
						String classType = method[i].getParameters()[0].getParameterizedType().toString();
						if (classType.contains("int")) {
							method[i].invoke(obj, rs.getInt(field)); // 用方法反调用
						} else if (classType.contains("String")) {
							method[i].invoke(obj, rs.getString(field));
						}
					}
				}
				list.add(obj);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;

	}

}
